package com.cn.xc.utils;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * FUN: character encoding tools class
 * 
 * @author sushy
 * @date 2016-3-23
 */
public class DecoderUtil {

	/**
	 * //# encoding string ,default UTF-8
	 * 
	 * @param str
	 * @return
	 */
	public static String decode(String str) {
		return decode(str, "utf-8");
	}

	/**
	 * //# encoding string ,you can custom encode type
	 * 
	 * @param str
	 * @param encoding
	 * @return
	 */
	public static String decode(String str, String encoding) {
		if (StringUtil.isBlank(str)) {
			return str;
		}
		try {
			return URLDecoder.decode(str, encoding).trim();
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}

	/**
	 * //# encoding string[] ,default UTF-8
	 * 
	 * @param strs
	 * @return
	 */
	public static String[] decode(String[] strs) {
		if (ArrayUtil.isEmpty(strs)) {
			return strs;
		}
		for (int i = 0, len = strs.length; i < len; i++) {
			strs[i] = decode(strs[i]);
		}
		return strs;
	}

	/**
	 * //# encoding list ,default UTF-8
	 * 
	 * @param list
	 * @return
	 */
	public static List<String> decode(List<String> list) {
		if (CollectionUtil.isEmpty(list)) {
			return list;
		}
		for (int i = 0, len = list.size(); i < len; i++) {
			list.set(i, decode(list.get(i)));
		}
		return list;
	}

	/**
	 * //# encoding object ,default UTF-8
	 * 
	 * @param obj
	 * @return
	 */
	public static Object decode(Object obj) {
		if (null == obj) {
			return obj;
		}
		Field[] fields = obj.getClass().getDeclaredFields();
		if (ArrayUtil.isEmpty(fields)) {
			return obj;
		}
		for (Field field : fields) {
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			try {
				Object value = field.get(obj);
				if (isNotStringClass(value)) {
					continue;
				}
				field.set(obj, decode(value.toString()));
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return obj;
	}

	private static boolean isNotStringClass(Object value) {
		return null == value || value.getClass() != String.class;
	}

	/**
	 * //# encoding map ,default UTF-8
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map decode(Map map) {
		if (MapUtil.isEmpty(map)) {
			return map;
		}
		Set<?> keys = map.keySet();
		if (CollectionUtil.isEmpty(keys)) {
			return map;
		}
		for (Object key : keys) {
			Object value = map.get(key);
			if (isNotStringClass(value)) {
				continue;
			}
			map.put(key, decode(value.toString()));
		}
		return map;
	}

}
